signature AST_STRUCTS =
sig
    include ATOMS
end

signature AST =
sig
    include AST_STRUCTS

type pos = int
type id = Id.t

structure Binop:
          sig
              datatype t
                = Plus
                | Minus
                | Times
                | Divide
                | Modus
                | And
                | Or
                | Eq
                | Ne
                | Gt
                | Ge
                | Lt
                | Le
                  
              val toString: t -> string
          end

structure Tipe:
          sig
              datatype t
                = Int
                | Char
                | Void
                | Struct of Id.t
                | Enum of Id.t
                | Pointer of t
                | Array of t

              val numNodes: t -> int
              val toString: t -> string              
          end

structure Exp:
          sig
              type lval
              type bop
              datatype t
                = Call of Id.t * (t list) * pos
                | IntNum of Intl.t
                | Lval of lval
                | Binop of t * bop * t * pos
                | Not of t * pos
                         
              val toString: t -> string
          end
sharing type Binop.t = Exp.bop
                       
structure Lval:
          sig
              type exp
              datatype t
                = Var of Id.t * pos
                | Ptr of t * pos
                | Array of t * exp * pos
                | Struct of t * Id.t * pos
                | Pstruct of t * Id.t * pos
                           
              val toString: t -> string
          end
sharing type Exp.lval = Lval.t
sharing type Exp.t = Lval.exp

structure Dec:
          sig
              datatype t 
                = StructDec of {name: id,
                                fields: {name: id, ty : Tipe.t} list}
                | EnumDec of {name: id,
                              fields: id list}
                | VarDec of {name: id,
                             ty: Tipe.t}
                | FunDec of {name: id,
                             rettype: Tipe.t,
                             args: {name: id, ty: Tipe.t} list}
                            
              val toString: t -> string
          end
          
structure Stm:
          sig
              type dec
              type exp
              type lval
              datatype t
                = Assign of lval * exp * pos
                | Comp of {decs: dec list, stms: t list, pos: pos}
                | If of {condition: exp, thenn: t, elsee: t option, pos: pos}
                | While of {condition: exp, body: t, pos: pos}
                | Return of exp option * pos
                            
              val toString: t -> string
          end
sharing type Exp.t = Stm.exp
sharing type Lval.t = Stm.lval
sharing type Dec.t = Stm.dec

structure Fun:
          sig
              datatype t
                = T of {name: Id.t,
                        rettype: Tipe.t,
                        args: {name: Id.t, ty: Tipe.t} list,
                        stm: Stm.t}

              val toString: t -> string
          end

structure Top:
          sig
              type f
              type dec
              datatype t
                = Fun of f
                | Dec of dec

              val toString: t -> string
          end
sharing type Top.f = Fun.t
sharing type Top.dec = Dec.t

structure Program:
          sig
              type top
              datatype t
                = T of top list
                       
              val bogus: unit -> t
              val numNodes: t -> int
              val toString: t -> string
          end
sharing type Program.top = Top.t

end
